package com.lemon.smartsafety.utils.common;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Environment;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;

/**
 * Created by Cooliean on 15/8/16.
 */
public class ImageUtils {
    //压缩图片后的最大文件大小
    private static final int PHOTO_MAX_SIZE = 200;  //changed by Andrew.yin 2017/11/2

    /**
     * 写图片文件 在Android系统中，文件保存在 /data/data/PACKAGE_NAME/files 目录下
     *
     * @throws IOException
     */
    public static void saveImage(Context context, String fileName, Bitmap bitmap) throws IOException {
        saveImage(context, fileName, bitmap, 100);
    }

    public static void saveImage(Context context, String fileName, Bitmap bitmap, int quality) throws IOException {
        if (bitmap == null || fileName == null || context == null) return;

        FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(CompressFormat.JPEG, quality, stream);
        byte[] bytes = stream.toByteArray();
        fos.write(bytes);
        fos.close();
    }

    /**
     * 保存Bitmap成图片文件
     *
     * @param bitmap
     * @param filePath
     * @param quality
     */
    public static boolean saveBitmapToFile(Bitmap bitmap, String filePath, int quality) {
        if (bitmap == null || filePath == null) {
            return false;
        }
        if (quality > 100) {
            quality = 100;
        }
        File file = new File(filePath.substring(0, filePath.lastIndexOf(File.separator)));
        if (!file.exists()) {
            file.mkdirs();
        }
        BufferedOutputStream bos;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(filePath));
            bitmap.compress(CompressFormat.JPEG, quality, bos);
            bos.flush();
            bos.close();
        } catch (Exception e) {
        }
        return bitmap != null;
    }

    /**
     * 让Gallery上能马上看到该图片
     */
    private static void scanPhoto(Context ctx, String imgFileName) {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File file       = new File(imgFileName);
        Uri  contentUri = Uri.fromFile(file);
        mediaScanIntent.setData(contentUri);
        ctx.sendBroadcast(mediaScanIntent);
    }


    /**
     * 获取/data/data/PACKAGE_NAME/files bitmap
     *
     * @param context
     * @param fileName
     * @return
     */
    public static Bitmap getBitmap(Context context, String fileName) {
        FileInputStream fis    = null;
        Bitmap          bitmap = null;
        try {
            fis = context.openFileInput(fileName);
            bitmap = BitmapFactory.decodeStream(fis);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
            } catch (Exception e) {
            }
        }
        return bitmap;
    }

    /**
     * 获取bitmap
     *
     * @param filePath
     * @return
     */
    public static Bitmap getBitmapByPath(String filePath) {
        return getBitmapByPath(filePath, null);
    }

    public static Bitmap getBitmapByPath(String filePath, BitmapFactory.Options opts) {
        FileInputStream fis    = null;
        Bitmap          bitmap = null;
        try {
            File file = new File(filePath);
            fis = new FileInputStream(file);
            bitmap = BitmapFactory.decodeStream(fis, null, opts);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
            } catch (Exception e) {
            }
        }
        return bitmap;
    }

    /**
     * 获取bitmap
     *
     * @param file
     * @return
     */
    public static Bitmap getBitmapByFile(File file) {
        FileInputStream fis    = null;
        Bitmap          bitmap = null;
        try {
            fis = new FileInputStream(file);
            bitmap = BitmapFactory.decodeStream(fis);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
            } catch (Exception e) {
            }
        }
        return bitmap;
    }

    /**
     * 使用当前时间戳拼接一个唯一的文件名
     *
     * @return
     */
    public static String getTempFileName() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss_SS");
        String fileName = format.format(new Timestamp(System.currentTimeMillis()));
        return fileName;
    }

    /**
     * 获取照相机使用的目录
     *
     * @return
     */
    public static String getCamerPath() {
        return Environment.getExternalStorageDirectory() + File.separator + "FounderNews" + File.separator;
    }


    /**
     * 将Drawable转化为Bitmap
     *
     * @param drawable
     * @return
     */
    public static Bitmap drawableToBitmap(Drawable drawable) {
        int width  = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, drawable.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888 : Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, width, height);
        drawable.draw(canvas);
        return bitmap;

    }

    /**
     * 获得圆角图片的方法
     *
     * @param bitmap
     * @param roundPx 一般设成14
     * @return
     */
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {

        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int   color = 0xff424242;
        final Paint paint = new Paint();
        final Rect  rect  = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        return output;
    }

    /**
     * 获得带倒影的图片方法
     *
     * @param bitmap
     * @return
     */
    public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) {
        final int reflectionGap = 4;
        int       width         = bitmap.getWidth();
        int       height        = bitmap.getHeight();

        Matrix matrix = new Matrix();
        matrix.preScale(1, -1);

        Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height / 2, width, height / 2, matrix, false);

        Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Config.ARGB_8888);

        Canvas canvas = new Canvas(bitmapWithReflection);
        canvas.drawBitmap(bitmap, 0, 0, null);
        Paint deafalutPaint = new Paint();
        canvas.drawRect(0, height, width, height + reflectionGap, deafalutPaint);

        canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);

        Paint paint = new Paint();
        LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
        paint.setShader(shader);
        // Set the Transfer mode to be porter duff and destination in
        paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
        // Draw a rectangle using the paint with our linear gradient
        canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);

        return bitmapWithReflection;
    }


    /**
     * 将bitmap转化为drawable
     *
     * @param bitmap
     * @return
     */
    public static Drawable bitmapToDrawable(Bitmap bitmap) {
        Drawable drawable = new BitmapDrawable(bitmap);
        return drawable;
    }


    /**
     * 获取图片类型
     *
     * @param file
     * @return
     */
    public static String getImageType(File file) {
        if (file == null || !file.exists()) {
            return null;
        }
        InputStream in = null;
        try {
            in = new FileInputStream(file);
            String type = getImageType(in);
            return type;
        } catch (IOException e) {
            return null;
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
            }
        }
    }

    /**
     * 获取图片的类型信息
     *
     * @param in
     * @return
     * @see #getImageType(byte[])
     */
    public static String getImageType(InputStream in) {
        if (in == null) {
            return null;
        }
        try {
            byte[] bytes = new byte[8];
            in.read(bytes);
            return getImageType(bytes);
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 获取图片的类型信息
     *
     * @param bytes 2~8 byte at beginning of the image file
     * @return image mimetype or null if the file is not image
     */
    public static String getImageType(byte[] bytes) {
        if (isJPEG(bytes)) {
            return "image/jpeg";
        }
        if (isGIF(bytes)) {
            return "image/gif";
        }
        if (isPNG(bytes)) {
            return "image/png";
        }
        if (isBMP(bytes)) {
            return "application/x-bmp";
        }
        return null;
    }

    private static boolean isJPEG(byte[] b) {
        if (b.length < 2) {
            return false;
        }
        return (b[0] == (byte) 0xFF) && (b[1] == (byte) 0xD8);
    }

    private static boolean isGIF(byte[] b) {
        if (b.length < 6) {
            return false;
        }
        return b[0] == 'G' && b[1] == 'I' && b[2] == 'F' && b[3] == '8' && (b[4] == '7' || b[4] == '9') && b[5] == 'a';
    }

    private static boolean isPNG(byte[] b) {
        if (b.length < 8) {
            return false;
        }
        return (b[0] == (byte) 137 && b[1] == (byte) 80 && b[2] == (byte) 78 && b[3] == (byte) 71 && b[4] == (byte) 13 && b[5] == (byte) 10 && b[6] == (byte) 26 && b[7] == (byte) 10);
    }

    private static boolean isBMP(byte[] b) {
        if (b.length < 2) {
            return false;
        }
        return (b[0] == 0x42) && (b[1] == 0x4d);
    }


    /**
     * 压缩图片到指定的分辨率，暂时没有发现内存溢出的情况，推荐使用
     *
     * @param sourcePath 原路径
     * @param targetPath 目标路径
     * @param width      压缩后图片宽度
     * @param height     压缩后图片高度
     */
    public static boolean decodeBitmap(String sourcePath, String targetPath, int width, int height) {
        if (!FileUtil.checkFileExistAndNotZero(sourcePath)) {
            return false;
        }
        boolean success = false;
        byte[]  bytes   = decodeImageToBytes(sourcePath, width, height);
        if (bytes != null && bytes.length != 0) {
            success = byteToFile(bytes, targetPath);
        }
        return success;
    }

    public static Bitmap decodeBitmap(String sourcePath, int width, int height) {
        if (!FileUtil.checkFileExistAndNotZero(sourcePath)) {
            return null;
        }
        try {
            //吃出可能由于 像素0造成数组转换崩溃  即空对象容易出现NullPointerException
            byte[] bytes = decodeImageToBytes(sourcePath, width, height);
            if (bytes != null && bytes.length != 0) {
                return imageByteToBitmap(bytes);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return  null;
        }
        return null;
    }

    /**
     * 压缩图片到指定的分辨率，暂时没有发现内存溢出的情况，推荐使用
     *
     * @param sourcePath 原路径
     * @param targetPath 目标路径
     * @param width      压缩后图片宽度
     * @param height     压缩后图片高度
     */
    public static boolean decodeBitmap(String sourcePath, String targetPath, int width, int height, String water) {
        if (!FileUtil.checkFileExistAndNotZero(sourcePath)) {
            return false;
        }
        boolean success = false;
        byte[]  bytes   = decodeImageToBytes(sourcePath, width, height);
        if (bytes != null && bytes.length != 0) {
            Bitmap bitmap = imageByteToBitmap(bytes);
            if (bitmap != null) {
                Bitmap bitmap1 = watermarkBitmap(bitmap, null, water);
                success = saveBitmapToFile(bitmap1, targetPath, 80);
            }
        }
        return success;
    }

    // 加水印 也可以加文字
    public static Bitmap watermarkBitmap(Bitmap source, Bitmap watermark, String title) {
        if (source == null) {
            return null;
        }
        //需要处理图片太大造成的内存超过的问题,这里我的图片很小所以不写相应代码了
        //Bitmap src = BitmapFactory.decodeFile(path);
        int    w   = source.getWidth();
        int    h   = source.getHeight();
        //Log.d("watermarkBitmap", w + "= w");
        //Log.d("watermarkBitmap", h + "= h");

        if (w < 480) {
            int tempw = 480;
            int tempH = (h*tempw)/w;

            w = tempw;
            h = tempH;
        }
        //Log.d("watermarkBitmap", w + "= new w");
        //Log.d("watermarkBitmap", h + "= new h");

        //Bitmap newb= compress(src);// 创建一个新的和SRC长度宽度一样的位图
        /*
        //ALPHA_8：每个像素占用1byte内存（8位）
//ARGB_4444:每个像素占用2byte内存（16位）
//ARGB_8888:每个像素占用4byte内存（32位）
//RGB_565:每个像素占用2byte内存（16位）
//Android默认的颜色模式为ARGB_8888，这个颜色模式色彩最细腻，显示质量最高。但同样的，占用的内存
//也最大。也就意味着一个像素点占用4个字节的内存。我们来做一个简单的计算题：3200*2400*4 bytes
//=30M。如此惊人的数字！哪怕生命周期超不过10s，Android也不会答应的。
         */
        Bitmap newb = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);// 创建一个新的和SRC长度宽度一样的位图
        Canvas cv   = new Canvas(newb);
        cv.drawBitmap(source, 0, 0, null);// 在 0，0坐标开始画入src
        Paint paint = new Paint();
        //加入图片
        if (watermark != null) {
            int ww = watermark.getWidth();
            int wh = watermark.getHeight();
            paint.setAlpha(50);
            cv.drawBitmap(watermark, w - ww + 5, h - wh + 5, paint);// 在src的右下角画入水印
        }
        //加入文字
        if (title != null) {
            String    familyName = "宋体";
            Typeface  font       = Typeface.create(familyName, Typeface.BOLD);
            TextPaint textPaint  = new TextPaint();
            textPaint.setColor(Color.RED);
            textPaint.setTypeface(font);
            textPaint.setTextSize(20);
            //这里是自动换行的
            StaticLayout layout = new StaticLayout(title, textPaint, w, Layout.Alignment.ALIGN_NORMAL, 1.0F, 0.0F, true);
            layout.draw(cv);
            //文字就加左上角算了
            //cv.drawText(title,0,40,paint);
        }
        cv.save(Canvas.ALL_SAVE_FLAG);// 保存
        cv.restore();// 存储

        return newb;
    }


    /**
     * 压缩图片到指定的分辨率，暂时没有发现内存溢出的情况，推荐使用
     *
     * @param sourcePath
     */
    public static byte[] decodeImageToBytes(String sourcePath, int width, int height) {
        if (!FileUtil.checkFileExistAndNotZero(sourcePath)) {
            return null;
        }

        BitmapFactory.Options opts = null;
        FileInputStream       is   = null;
        Bitmap                bmp  = null;
        ByteArrayOutputStream baos = null;
        try {
            opts = new BitmapFactory.Options();
            opts.inJustDecodeBounds = true;// 设置成了true,不占用内存，只获取bitmap宽高
            BitmapFactory.decodeFile(sourcePath, opts);

            if (opts.outHeight < height || opts.outWidth < width) {//如果图片本身的宽高小于要压缩的高度，就直接取图片高度
                height = opts.outHeight;
                width = opts.outWidth;
            }
            opts.inSampleSize = computeSampleSize(opts, -1, width * height);
            //        options.inSampleSize = inSampleSize;
            //        calculateInSampleSize(options, rewidth, reheight);
            opts.inJustDecodeBounds = false;// 这里一定要将其设置回false，因为之前我们将其设置成了true
            opts.inPurgeable = true;
            opts.inInputShareable = true;
            opts.inDither = false;
            opts.inPurgeable = true;
            opts.inTempStorage = new byte[16 * 1024];
            is = null;
            bmp = null;
            baos = null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }


        try {
            is = new FileInputStream(sourcePath);
            bmp = BitmapFactory.decodeFileDescriptor(is.getFD(), null, opts);
            double scale = getScaling(opts.outWidth * opts.outHeight, width * height);
            Bitmap bmp2 = Bitmap.createScaledBitmap(bmp, (int) (opts.outWidth * scale), (int) (opts.outHeight * scale), true);
            //            bmp.recycle();
            baos = new ByteArrayOutputStream();
            bmp2.compress(CompressFormat.JPEG, 100, baos);
            //这里循环控制让图片小于200K
            int options = 100;
            while ((baos.size() / 1024) > PHOTO_MAX_SIZE) {
                baos.reset();
                options -= 2;
                if (options < 0) {//这里是为了防止质量低于0了，图片大小还是不满足条件的情况
                    options = 90;
                }
                bmp2.compress(CompressFormat.JPEG, options, baos);// 这里压缩options%，把压缩后的数据存放到baos中
            }
            bmp.recycle();
            bmp2.recycle();
            return baos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (baos != null) {
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.gc();
        }
        return baos.toByteArray();
    }


    /**
     * bytes 转bitmap
     *
     * @param bytes
     * @return
     */
    public static Bitmap imageByteToBitmap(byte[] bytes) {
        InputStream           input   = null;
        Bitmap                bitmap  = null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 1;
        input = new ByteArrayInputStream(bytes);
        SoftReference softRef = new SoftReference(BitmapFactory.decodeStream(input, null, options));
        bitmap = (Bitmap) softRef.get();
        return bitmap;

    }

    public static boolean byteToFile(byte[] bytes, String savePath) {
        // 预览图片的文件名
        FileOutputStream foStream = null;
        boolean          success  = true;
        try {
            foStream = new FileOutputStream(savePath);
            foStream.write(bytes);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            success = false;
        } catch (IOException e) {
            e.printStackTrace();
            success = false;
        } finally {
            if (foStream != null) {
                try {
                    foStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    success = false;
                }
            }
        }
        return success;
    }


    private static double getScaling(int src, int des) {
        /**
         * 目标尺寸÷原尺寸 sqrt开方，得出宽高百分比
         */
        double scale = Math.sqrt((double) des / (double) src);
        return scale;
    }

    public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
        int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);

        int roundedSize;
        if (initialSize <= 8) {
            roundedSize = 1;
            while (roundedSize < initialSize) {
                roundedSize <<= 1;
            }
        } else {
            roundedSize = (initialSize + 7) / 8 * 8;
        }

        return roundedSize;
    }

    private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
        double w = options.outWidth;
        double h = options.outHeight;

        int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
        int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));

        if (upperBound < lowerBound) {
            return lowerBound;
        }

        if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
            return 1;
        } else if (minSideLength == -1) {
            return lowerBound;
        } else {
            return upperBound;
        }
    }


    /**
     * 根据图片路径进行Base64编码处理
     *
     * @param filePath
     * @return
     */
    public static String getImageBase64Code(String filePath) {
        String result = "";
        try {
            byte[] buffer = FileUtil.toBytes(filePath);
            result = Base64.encodeToString(buffer, Base64.DEFAULT);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 读取图片属性：旋转的角度
     *
     * @param path 图片绝对路径
     * @return degree旋转的角度
     */
    public static int readPictureDegree(String path) {
        int degree = 0;
        if (path == null) {
            return 0;
        }
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 对Bitmap做旋转操作
     *
     * @param bm
     * @param orientationDegree
     * @return
     */
    public static Bitmap adjustPhotoRotation(Bitmap bm, final int orientationDegree) {
        if (bm == null) {
            return null;
        }
        Matrix m = new Matrix();
        m.setRotate(orientationDegree, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
        float targetX, targetY;
        if (orientationDegree == 90) {
            targetX = bm.getHeight();
            targetY = 0;
        } else {
            targetX = bm.getHeight();
            targetY = bm.getWidth();
        }

        final float[] values = new float[9];
        m.getValues(values);

        float x1 = values[Matrix.MTRANS_X];
        float y1 = values[Matrix.MTRANS_Y];

        m.postTranslate(targetX - x1, targetY - y1);

        Bitmap bm1    = Bitmap.createBitmap(bm.getHeight(), bm.getWidth(), Config.RGB_565);
        Paint  paint  = new Paint();
        Canvas canvas = new Canvas(bm1);
        canvas.drawBitmap(bm, m, paint);

        return bm1;
    }
}
